#include <uci.h>
#include "udp_service.h"
#include "data_type.h"
#include "ep_gpio.h"
#include "redis_util.h"
#include "lte_service.h"
#include "iot_service.h"
#include "yunw_mesh_service.h"

#define UCI_MQTT_CONFIG_FILE "/etc/config/idc_mqtt"
#define UCI_APP_CONFIG_FILE "/etc/config/idc_app"
#define NUM_THREADS
#define DEBUG   1

t_RunCfg runCfg;
bool app_init = false;
struct blob_buf b;

void idc_load_app_cfg();
void idc_load_mqtt_cfg();
int ubus_invoke_get_lora_addr();

void init(){
    // ep_gpio_export(448);
    // ep_gpio_direction(448,2);
    idc_load_app_cfg();
    idc_load_mqtt_cfg();
    ubus_invoke_get_lora_addr();
}
int main(int argc, char* argv[])
{
    init();
    // ep_mqtt_sub_start();
    // lora_worker_start();
    // ubus_worker_start();
    // udp_worker_start();
    while(!app_init);
    // yunw_mesh_worker_start();
    iot_worker_start();
    bridge_worker_start();
    lte_worker_start();
    yunw_mesh_worker_start();
    while (true)
    {
        sleep(1);
    }
}
/*********************************************
* 载入配置文件,并遍历Section.
*/
void idc_load_app_cfg()
{
    struct uci_package * pkg = NULL;
    struct uci_element *e;
    struct uci_context * ctx = NULL;
    char *tmp;
    const char *value;

    ctx = uci_alloc_context(); // 申请一个UCI上下文.
    if (UCI_OK != uci_load(ctx, UCI_APP_CONFIG_FILE, &pkg))
        goto cleanup; //如果打开UCI文件失败,则跳到末尾 清理 UCI 上下文.


    /*遍历UCI的每一个节*/
    uci_foreach_element(&pkg->sections, e)
    {
        struct uci_section *s = uci_to_section(e);
        printf("type: %s\n", s->type);
        if(!strcmp("conf",s->type)) //this section is a meter
        {
            if (NULL != (value = uci_lookup_option_string(ctx, s, "iot_enable")))
            {
                printf("iot_enable:%s\n", strdup(value));
                runCfg.iot_enable = strdup(value);
            }
            if (NULL != (value = uci_lookup_option_string(ctx, s, "bridge_enable")))
            {
                printf("bridge_enable:%s\n", strdup(value));
                runCfg.bridge_enable = strdup(value);
            }
            if (NULL != (value = uci_lookup_option_string(ctx, s, "lte_enable")))
            {
                printf("lte_enable:%s\n", strdup(value));
                runCfg.lte_enable = strdup(value);
            }
            if (NULL != (value = uci_lookup_option_string(ctx, s, "mesh_enable")))
            {
                printf("mesh_enable:%s\n", strdup(value));
                runCfg.mesh_enable = strdup(value);
            }
        }

    }
    uci_unload(ctx, pkg); // 释放 pkg
    cleanup:
    uci_free_context(ctx);
    ctx = NULL;
}
void idc_load_mqtt_cfg()
{
    struct uci_package * pkg = NULL;
    struct uci_element *e;
    struct uci_context * ctx = NULL;
    char *tmp;
    const char *value;

    ctx = uci_alloc_context(); // 申请一个UCI上下文.
    if (UCI_OK != uci_load(ctx, UCI_MQTT_CONFIG_FILE, &pkg))
        goto cleanup; //如果打开UCI文件失败,则跳到末尾 清理 UCI 上下文.


    /*遍历UCI的每一个节*/
    uci_foreach_element(&pkg->sections, e)
    {
        struct uci_section *s = uci_to_section(e);
        printf("type: %s\n", s->type);
        if(!strcmp("conf",s->type)) //this section is a meter
        {
            if (NULL != (value = uci_lookup_option_string(ctx, s, "sn")))
            {
                printf("sn:%s\n", strdup(value));
                runCfg.sn = strdup(value);
            }
        }
    }
    uci_unload(ctx, pkg); // 释放 pkg
    cleanup:
    uci_free_context(ctx);
    ctx = NULL;
}

const struct blobmsg_policy lora_addr_policy[] = {
        [0] = { .name = "addr", .type = BLOBMSG_TYPE_INT32 },
        [1] = { .name = "group_addr", .type = BLOBMSG_TYPE_INT32 },
        [2] = { .name = "is_center", .type = BLOBMSG_TYPE_INT32 },
}; 
const struct blobmsg_policy energy_info_policy[] = {
        [0] = { .name = "addr", .type = BLOBMSG_TYPE_INT32 },
        [1] = { .name = "date", .type = BLOBMSG_TYPE_STRING },
        [2] = { .name = "time", .type = BLOBMSG_TYPE_STRING },
        [3] = { .name = "sleep_time", .type = BLOBMSG_TYPE_STRING },
        [4] = { .name = "work_time", .type = BLOBMSG_TYPE_STRING },
}; 

void get_lora_addr_callback(struct ubus_request *req, int type, struct blob_attr *msg) {
        if (!msg) {
                return;
        }
        struct blob_attr *tb[3];
        blobmsg_parse(lora_addr_policy, ARRAY_SIZE(lora_addr_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));
        if(tb[0]){
            runCfg.lora_addr = blobmsg_get_u32(tb[0]);
        }
        if(tb[1]){
            runCfg.lora_group = blobmsg_get_u32(tb[1]);
        }
        printf("lora_addr:%04X,lora_group:%04X\n", runCfg.lora_addr, runCfg.lora_group);
        app_init = true;
}
void get_energy_info_callback(struct ubus_request *req, int type, struct blob_attr *msg) {
        if (!msg) {
                return;
        }
        struct blob_attr *tb[5];
        blobmsg_parse(energy_info_policy, ARRAY_SIZE(energy_info_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));
        if(tb[3]){
            uint8_t *sleep_time = blobmsg_get_string(tb[3]);
            memset(runCfg.sleep_time, 0, 9);
            memcpy(runCfg.sleep_time, sleep_time, strlen(sleep_time));
        }
        if(tb[4]){
            uint8_t *work_time = blobmsg_get_string(tb[4]);
            memset(runCfg.work_time, 0, 9);
            memcpy(runCfg.work_time, work_time, strlen(work_time));
        }
        printf("sleep_time:%s,work_time:%s\n", runCfg.sleep_time, runCfg.work_time);
        app_init = true;
}
/**
 * 调用Energy服务,获取Lora地址信息
 */
int ubus_invoke_get_lora_addr() {
    // 连接 ubus
    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "Failed to connect to ubus\n");
        return -1;
    }
    // 查找 network.device 的 ID
    uint32_t obj_id;
    if (ubus_lookup_id(ctx, "sihan.energy", &obj_id) != 0) {
        fprintf(stderr, "Failed to lookup sihan.energy\n");
        ubus_free(ctx);
        return -1;
    }

    blob_buf_init(&b, 0);
    
    // 发起异步调用
    int ret = ubus_invoke(ctx, obj_id, "query_addr", b.head, get_lora_addr_callback, 0, 3000);
    if (ret == 0) {}
    ret = ubus_invoke(ctx, obj_id, "query_timeinfo", b.head, get_energy_info_callback, 0, 3000);
    if (ret == 0) {}
    // 清理资源
    blob_buf_free(&b);
    ubus_free(ctx);
    return 0;
}


